import 'dart:io';
import 'dart:convert';
import 'package:common_utils/common_utils.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:part_time_job_pro/common/exception/auth_interceptor.dart';
import 'package:part_time_job_pro/common/exception/exp_handler.dart';
import 'package:part_time_job_pro/common/values/server_config.dart';
import 'package:part_time_job_pro/common/values/storage.dart';

import '../values/proxy.dart';

//文件标题
String title = "Request Utils";

///网络请求处理
class RequestUtil {
  static RequestUtil? instance;

  //创建实例
  static Dio? _dio;

  //取消token
  //CancelToken cancelToken = CancelToken();
  //获取实例
  static RequestUtil getInstance() {
    Map<String, dynamic> headers = {
      "platform": Platform.isAndroid ? "android" : "ios",
      "appcode": appCode,
      "appverion": appVersion,
    };
    LogUtil.e("<<<<<<====实例化request成功!===>>>>>");
    return instance ?? RequestUtil(headers: headers);
  }

  /*
   * 构造函数 设置头部参数
   */
  RequestUtil({Map<String, dynamic>? headers}) {
    // 配置 Dio 实例
    BaseOptions options = BaseOptions(
      baseUrl: HttpConfig.serverUrl,
      headers: headers,
      connectTimeout: const Duration(milliseconds: HttpConfig.connectTimeOut),
      receiveTimeout: const Duration(milliseconds: HttpConfig.receiveTimeout),
      //请求的Content-Type，默认值是"application/json; charset=utf-8",Headers.formUrlEncodedContentType会自动编码请求体.
      contentType: Headers.formUrlEncodedContentType,
      //表示期望以那种格式(方式)接受响应数据。接受四种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
      responseType: ResponseType.plain,
    );

    _dio = Dio(options);
    //Cookie管理
    _dio?.interceptors.add(CookieManager(CookieJar()));
    //统一添加身份验证请求头
    _dio?.interceptors.add(AuthInterceptor());
    //统一日志打印上传处理
    //_dio?.interceptors.add(AppLogInterceptor());

    //设置代理
    if(PROXY_ENABLE) {
      (_dio?.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
          (client) {
        client.findProxy = (url) {
          ///设置代理 电脑ip地址:端口号
          return "PROXY $PROXY_IP:$PROXY_PORT";
          //不设置代理
          //return 'DIRECT';
        };

        ///忽略证书
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
        return null;
      };
    }
  }

  // _request 是核心函数，处理所有的请求
  Future _request(String path,
      {String? method, Map? params, data, cancelToken, decode = false}) async {
    // restful 请求处理
    if (params != null) {
      params.forEach((key, value) {
        if (path.contains(key)) {
          path = path.replaceAll(":$key", value.toString());
        }
      });
    }

    LogUtil.e(data, tag: '发送的数据为：');
    try {
      Response? response = await _dio?.request(path,
          data: data,
          cancelToken: cancelToken,
          options: Options(method: method));
      final responseData = response?.data;
      LogUtil.e(responseData, tag: '响应的数据为：');
      if (decode) {
        return json.decode(responseData);
      } else {
        return responseData;
      }
    } on DioException catch (e) {
      return ExceptionHandler.handleDioError(e);
    } catch (e) {
      return ExceptionHandler.handleHttpError(e);
    }
  }

  //发送get请求
  Future get(String path, {Map? params, decode = false, cancelToken}) {
    return _request(path,
        method: 'get',
        params: params,
        decode: decode,
        cancelToken: cancelToken);
  }

  //发送post请求
  Future post(String path, {Map? params, decode = false, data, cancelToken}) {
    return _request(path,
        method: 'post',
        params: params,
        decode: decode,
        data: data,
        cancelToken: cancelToken);
  }

  //发送put请求
  Future put(String path, {Map? params, decode = false, data, cancelToken}) {
    return _request(path,
        method: 'put',
        params: params,
        decode: decode,
        data: data,
        cancelToken: cancelToken);
  }

  //发送delete请求
  Future delete(String path, {Map? params, decode = false, cancelToken}) {
    return _request(path,
        method: 'delete',
        params: params,
        decode: decode,
        cancelToken: cancelToken);
  }

  /*
   * 取消请求
   * 同一个cancel token 可以用于多个请求，当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
   * 所以参数可选
   */
  void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }

  //处理登录失效
  void dealTokenExppireLoginOut(result) {}
}
